package AG;

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class AG {

	private static final int POPULATION = 10;
	private static final int GENERATIONS = 5000;
	
	private List<DNA> population;
	
	public static void main(String[] args) {
		try {
			System.setOut(new SuppressedPrintStream());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		new AG();
	}
	
	private AG(){
		population = new ArrayList<DNA>();
		do {
			population.add(new DNA());
		}while(population.size()<POPULATION);
		
		Collections.sort(population);
		
		for (int i = 0; i < GENERATIONS; i++) {
			System.err.println("Generation: " + i);
			for (DNA dna : population) {
				System.err.println(dna.evaluateDNA() + " " + dna);
			}
			//<selecao>1000
			DNA a = selectToReproduce();
			DNA b = selectToReproduce();
			//</selecao>
			//<reproducao>
			DNA childa = a.reproduce(b);
			DNA childb = b.reproduce(a);
			//</reproducao>
			//<mutacao>
			childa.mutate();
			childb.mutate();
			//</mutacao>
			//<reinclussao>
			population.add(childa);
			population.add(childb);
			//<reinclusao>

			populationControl();

		}
		System.err.printf("%.10f\n", population.get(0));
		System.err.println(population.get(0));
	}
	private void populationControl() {
		Collections.sort(population);
		for (int i = 0 ; i < population.size()-1 ; i++) {
			while (((i+1)<population.size()) && population.get(i).equals(population.get(i+1))) {
				population.remove(i+1);
			}
		}
		while (population.size() > POPULATION)
			population.remove(POPULATION);
	}

	private DNA selectToReproduce() {
		
		double sum = populationSum();
		double select = Math.random();
		double walk = 0.0;
		for (DNA dna : population) {
			walk += (dna.evaluateDNA()/sum);
			if (select < walk) {
				return dna;
			}
		}
		return null;
	}

	private double populationSum() {
		double sum = 0.0;
		for (DNA dna : population) {
			sum+=dna.evaluateDNA();
		}
		return sum;
	}
}

class SuppressedPrintStream extends PrintStream {

	public SuppressedPrintStream() throws FileNotFoundException {
		super("a");//efeito colateral, cria um arquivo
	}
	public void print(boolean b) {}
	public void print(char c) {}
	public void print(char[] s) {}
	public void print(double d) {}
	public void print(float f) {}
	public void print(int i) {}
	public void print(long l) {};	
	public void print(Object obj) {};
	public void print(String s) {};
	public void println() {};
	public void println(boolean x) {};
	public void println(char x) {};
	public void println(char[] x) {};
	public void println(double x) {};
	public void println(float x) {};
	public void println(int x) {};
	public void println(long x) {};
	public void println(Object x) {};
	public void println(String x) {};
	
}
